package cConsole

import (
	"fmt"
	"os"
	"reflect"
	"regexp"
	"strings"

	"github.com/fatih/color"
)

func load() (cmd, method string, params map[string]string) {
	var commandArgument string
	var paramArgs []string
	var reg = regexp.MustCompile(`^[\w_\-]+::[\w_\-]+$`)

	argsCount := len(os.Args)
	if argsCount == 1 {
		commandArgument = "help::doc"
	} else if argsCount == 2 {
		if !reg.Match([]byte(os.Args[1])) {
			commandArgument = "help::doc"
		} else {
			commandArgument = os.Args[1]
		}
	} else {
		commandArgument = os.Args[1]
		paramArgs = os.Args[2:]
	}

	// var cmd, method string
	params = make(map[string]string)
	var argReg = regexp.MustCompile(`^--[\w_]+=`)

	commandArgs := strings.Split(commandArgument, "::")
	cmd = commandArgs[0]
	method = commandArgs[1]

	for _, arg := range paramArgs {
		if !argReg.Match([]byte(arg)) {
			continue
		}
		tempParams := strings.Split(arg, "=")
		key := strings.TrimPrefix(tempParams[0], "--")
		val := tempParams[1]
		params[key] = val
	}

	container.SetConsole(cmd, method, params)

	container.Save(&HelpConsole{})

	return
}

func Run() {
	console := container.GetConsole()

	cmd := console.Cmd
	method := console.Method
	params := console.Params

	instance := container.Get(cmd)
	// 判断指令是否存在
	if instance == nil {
		color.Set(color.FgHiRed)
		fmt.Printf("指令【%s::%s】不存在! 请使用【help::doc】获取帮助 或者 使用【version::update】更新工具.\n", cmd, method)
		color.Set(color.FgWhite)
		return
	}

	var methodName string
	desc := instance.(ConsoleInterface).Desc()
	methodName = strings.Title(method)
	for _, consoleMethod := range desc.Methods {
		if method == consoleMethod.Name && consoleMethod.Method != "" {
			methodName = consoleMethod.Method
			break
		}
	}

	// 判断指令方法是否存在
	_, exists := reflect.TypeOf(instance).MethodByName(methodName)
	if !exists {
		color.Set(color.FgHiRed)
		fmt.Printf("指令【%s::%s】方法错误! 请使用【help::doc】获取帮助 或者 使用【version::update】更新工具.\n", cmd, method)
		color.Set(color.FgWhite)
		return
	}

	var callParams []reflect.Value
	paramNames := container.GetParams(cmd, method)
	for _, name := range paramNames {
		if _, ok := params[name]; ok {
			callParams = append(callParams, reflect.ValueOf(params[name]))
		} else {
			callParams = append(callParams, reflect.ValueOf(""))
		}
	}

	m := reflect.ValueOf(instance).MethodByName(methodName)
	m.Call(callParams)
}
